﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Util
{
    /// <summary>
    /// 安全辅助类
    /// </summary>
    public static class SecurityHelper
    {
        #region 加密：Encrypt

        public static string Key64 = "FEIWUWL2";//注意了，是8个字符，64位
        public static string Iv64 = "FEIWUWL2";

        /// <summary>
        /// 加密数据 ： 可逆 对应 Decrypt
        /// </summary>
        /// <param name="data">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string Encrypt(string data, string key = "")
        {
            if (string.IsNullOrWhiteSpace(key))
                key = Key64;
            var byKey = Encoding.ASCII.GetBytes(key);
            var byIv = Encoding.ASCII.GetBytes(key);
            var cryptoProvider = new DESCryptoServiceProvider();
            var ms = new MemoryStream();
            var cst = new CryptoStream(ms, cryptoProvider.CreateEncryptor(byKey, byIv), CryptoStreamMode.Write);
            var sw = new StreamWriter(cst);
            sw.Write(data);
            sw.Flush();
            cst.FlushFinalBlock();
            sw.Flush();
            return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
        }

        #endregion

        #region 解密：Decrypt

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="data">要解密的数据</param>
        /// <returns>解密后的数据</returns>
        public static string Decrypt(string data, string key = "")
        {
            //处理+ 号
            if (string.IsNullOrWhiteSpace(key))
                key = Key64;
            var dt = data.Replace(' ', '+');
            var byKey = Encoding.ASCII.GetBytes(Key64);
            var byIv = Encoding.ASCII.GetBytes(Iv64);
            byte[] byEnc;
            try
            {
                byEnc = Convert.FromBase64String(dt);
            }
            catch
            {
                return data;
            }
            var cryptoProvider = new DESCryptoServiceProvider();
            var ms = new MemoryStream(byEnc);
            var cst = new CryptoStream(ms, cryptoProvider.CreateDecryptor(byKey, byIv), CryptoStreamMode.Read);
            var sr = new StreamReader(cst);
            return sr.ReadToEnd();
        }

        #endregion

        #region Md5加密：Md5

        /// <summary>
        /// Md5加密
        /// </summary>
        /// <param name="text">要加密的内容</param>
        /// <returns></returns>
        public static string Md5(string text)
        {
            // 第三步：使用MD5加密
            var md5 = MD5.Create();
            byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(text));

            var result = new StringBuilder();
            foreach (byte t in bytes)
            {
                string hex = t.ToString("X");
                if (hex.Length == 1)
                {
                    result.Append("0");
                }
                result.Append(hex);
            }

            return result.ToString();
        }
        /// <summary>
        /// 标准MD5加密
        /// </summary>
        /// <param name="strVal"></param>
        /// <returns></returns>
        public static string Md5Encrypt(string strVal)
        {
            string ret = string.Empty;
            byte[] b = Encoding.UTF8.GetBytes(strVal);
            b = new MD5CryptoServiceProvider().ComputeHash(b);
            return b.Aggregate(ret, (current, t) => current + t.ToString("x").PadLeft(2, '0'));
        }
        #endregion

        #region SHA256加密：SHA256

        /// <summary>
        /// SHA256加密
        /// </summary>
        /// <param name="data">加密数据</param>
        /// <returns></returns>
        public static string SHA256(string data)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(data);
            byte[] hash = System.Security.Cryptography.SHA256.Create().ComputeHash(bytes);

            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("X2"));
            }

            return builder.ToString();
        }

        #endregion

        #region 签名：Sign

        /// <summary>
        /// 签名
        /// </summary>
        /// <param name="appKey">应用key</param>
        /// <param name="timeStamp">时间戳</param>
        /// <param name="version">版本</param>
        /// <param name="appSecret">密钥</param>
        /// <returns>签名字符串</returns>
        public static string Sign(string appKey, string timeStamp, string version, string appSecret)
        {
            var dictionary = new Dictionary<string, string>
                {
                    {"apiVersion", version},
                    {"appKey", appKey},
                    {"timeStamp", timeStamp}
                };
            // 第一步：把字典按Key的字母顺序排序
            IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(dictionary);
            IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();

            // 第二步：把所有参数名和参数值串在一起
            var query = new StringBuilder(appSecret);
            while (dem.MoveNext())
            {
                string key = dem.Current.Key;
                string value = dem.Current.Value;
                if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
                {
                    query.Append(key).Append(value);
                }
            }

            // 第三步：使用MD5加密
            var result = Md5(query.ToString());
            return result;
        }

        #endregion

        /// <summary>
        /// 密码加密
        /// </summary>
        /// <param name="password">密码</param>
        /// <param name="salt">附加码</param>
        /// <returns></returns>
        public static string GetPwd(string password, string salt)
        {
            return Md5Encrypt(Md5Encrypt(password + salt));
        }

        /// <summary>
        /// 密码加密
        /// </summary>
        /// <param name="password">密码</param>
        /// <param name="salt">附加码</param>
        /// <returns></returns>
        public static string GetTeacherPwd(string password, string salt)
        {
            return Md5(password + salt);
        }

        /// <summary>
        /// 密码加密 学生
        /// </summary>
        /// <param name="password">密码</param>
        /// <param name="salt">附加码</param>
        /// <returns></returns>
        public static string GetStuPwd(string password, string salt)
        {
            return Md5Encrypt(Md5Encrypt(password + salt));
        }
    }
}
